#include "FunTrace.h"
#include <http.h>
#include "iris.h"

#include <aknglobalnote.h> 

static void PrintNoteL(TRefByValue<const TDesC> aFormat, ...)
    {
    VA_LIST list;
    VA_START(list, aFormat);
    TBuf<256> buf;
    buf.FormatList(aFormat, list);
    VA_END(list);
	CAknGlobalNote* globalNote = CAknGlobalNote::NewLC();
	globalNote->ShowNoteL(EAknGlobalInformationNote, buf); 
    CleanupStack::PopAndDestroy(globalNote);
    }


static void SetCookie(RHTTPSession& aSession, RHTTPRequest aRequest, const TDesC8& aCookieName, const TDesC8& aCookieValue)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	RStringPool string_pool = aSession.StringPool();
	RHTTPHeaders headers = aRequest.GetHeaderCollection();
	RStringF cookie_rsf = string_pool.StringF(HTTP::ECookie,RHTTPSession::GetTable());
	THTTPHdrVal field_value;
	field_value.SetStrF (cookie_rsf);
	headers.SetFieldL(cookie_rsf, field_value);
	
	THTTPHdrVal cookie_hdr;
	RStringF cookie_name_rsf = string_pool.StringF(HTTP::ECookieName,RHTTPSession::GetTable());
	RString name = string_pool.OpenStringL (aCookieName);
	cookie_hdr.SetStr (name);
	headers.SetParamL (cookie_rsf, cookie_name_rsf, cookie_hdr, 0);
	name.Close();
	
	RStringF cookie_value_rsf = string_pool.StringF(HTTP::ECookieValue,RHTTPSession::GetTable());
	RString value = string_pool.OpenStringL(aCookieValue);
	cookie_hdr.SetStr (value);
	headers.SetParamL (cookie_rsf, cookie_value_rsf, cookie_hdr, 0); 
	value.Close();
	}

void RHTTPRequestSetCookie(RHTTPSession& aSession, RHTTPRequest aRequest, const TDesC8& aCookieName, const TDesC8& aCookieValue)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	RStringPool string_pool = aSession.StringPool();
	RHTTPHeaders headers = aRequest.GetHeaderCollection();
	RStringF cookie_rsf = string_pool.StringF(HTTP::ECookie,RHTTPSession::GetTable());
	THTTPHdrVal field_value;
	field_value.SetStrF (cookie_rsf);
	headers.SetFieldL(cookie_rsf, field_value);
	
	THTTPHdrVal cookie_hdr;
	RStringF cookie_name_rsf = string_pool.StringF(HTTP::ECookieName,RHTTPSession::GetTable());
	RString name = string_pool.OpenStringL (aCookieName);
	cookie_hdr.SetStr (name);
	headers.SetParamL (cookie_rsf, cookie_name_rsf, cookie_hdr, 0);
	name.Close();
	
	RStringF cookie_value_rsf = string_pool.StringF(HTTP::ECookieValue,RHTTPSession::GetTable());
	RString value = string_pool.OpenStringL(aCookieValue);
	cookie_hdr.SetStr (value);
	headers.SetParamL (cookie_rsf, cookie_value_rsf, cookie_hdr, 0); 
	value.Close();
	}

HBufC8* RHTTPRequestGetCookie(RHTTPSession& aSession, RHTTPResponse aResponse, const TDesC8& aCookieName)
{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	RStringF strCookieField = aSession.StringPool().StringF(HTTP::ESetCookie, RHTTPSession::GetTable ( ) );
	THTTPHdrVal valCookieName, valCookieValue;
	RStringF strCookieName = aSession.StringPool().StringF(HTTP::ECookieName, RHTTPSession::GetTable ( ) );
	RStringF strCookieValue = aSession.StringPool().StringF(HTTP::ECookieValue, RHTTPSession::GetTable ( ) );
	if( aResponse.GetHeaderCollection().GetParam(strCookieField, strCookieName, valCookieName) == KErrNone &&
		valCookieName.Str().DesC() == aCookieName &&
		aResponse.GetHeaderCollection().GetParam(strCookieField, strCookieValue, valCookieValue) == KErrNone
		)
		{
		return valCookieValue.Str().DesC().AllocL();
		}
	return NULL;
}

// *****************

CHTTPTransactionTarget* CHTTPTransactionTarget::NewLC()
{
TFunTrace funTrace(__PRETTY_FUNCTION__);
CHTTPTransactionTarget* ret = new (ELeave) CHTTPTransactionTarget;
	CleanupStack::PushL(ret);
	ret->ConstructL();
	return ret;
}

CHTTPTransactionTarget* CHTTPTransactionTarget::NewL()
{
TFunTrace funTrace(__PRETTY_FUNCTION__);
CHTTPTransactionTarget* ret = NewLC();
	CleanupStack::Pop(ret);
	return ret;
}

void CHTTPTransactionTarget::ConstructL()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	iBody.CreateL(1024);	
	}


CHTTPTransactionTarget::CHTTPTransactionTarget() : iRun(NULL), iRunError(NULL), iRunBodyData(NULL)
	{
	
	}

void CHTTPTransactionTarget::SetRun(scalp::CFunction<void(RHTTPTransaction, THTTPEvent, TInt, TPtrC8)>* aRun)
{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	delete iRun;
	iRun = aRun;
}

void CHTTPTransactionTarget::SetRunBodyData(scalp::CFunction<void(RHTTPTransaction, THTTPEvent, TInt, TPtrC8, TInt)>* aRunBodyData)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	delete iRunBodyData;
	iRunBodyData = aRunBodyData;
	}


void CHTTPTransactionTarget::SetRunError(scalp::CFunction<TInt(TInt, RHTTPTransaction, THTTPEvent)>* aRunError)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	delete iRunError;
	iRunError = aRunError;	
	}

void CHTTPTransactionTarget::MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent)
{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	
if(aEvent.iStatus < KErrNone) iLastError = aEvent.iStatus;
	  switch (aEvent.iStatus)
		{
		case THTTPEvent::EUnrecoverableError:
			iLastError = KErrNotReady; // for Symbian 5th ed + 
		  break;
			  
		case THTTPEvent::EGotResponseHeaders:
			{
			iBody.Zero();
			iLastError = KErrNone;
			}
		  break;

		case THTTPEvent::EGotResponseBodyData:
			{
		      MHTTPDataSupplier* body = aTransaction.Response().Body();
		      TPtrC8 part;
		      body->GetNextDataPart(part);
		      TInt partLength = part.Length();
		      if(part.Length() + iBody.Length() > iBody.MaxLength() )
		    	  iBody.ReAllocL(part.Length() + iBody.Length());	    	  	    	  
	    	  iBody.Append(part);	    	  	    	  
		      body->ReleaseData();
		      if(iRunBodyData)
		    	  (*iRunBodyData)(aTransaction, aEvent, iLastError, iBody, partLength);
		    	  
			}
		  break;

		case THTTPEvent::EResponseComplete:
		  break;

		case THTTPEvent::ESucceeded:
		case THTTPEvent::EFailed:
			{
			(*iRun)(aTransaction, aEvent, iLastError, iBody);
			}			
		  break;

		case THTTPEvent::ERedirectedPermanently:
			{
			}
		  break;
			
		case THTTPEvent::ERedirectedTemporarily:
			{
			}
		  break;
			
		default:
			{
			
			}
		  break;
		}
}
TInt CHTTPTransactionTarget::MHFRunError(TInt aError, RHTTPTransaction aTransaction, const THTTPEvent& aEvent)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	if(iRunError)
		return (*iRunError)(aError, aTransaction, aEvent);
	else
		return aError;
	}
CHTTPTransactionTarget::~CHTTPTransactionTarget()
{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	delete iRun;
	delete iRunError;
	delete iRunBodyData;
	iBody.Close();
}

// *****************

void CHTTPTransactionSource::SetPostDataL(const TDesC8& aPostData)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	delete iPostData;
	iPostData = aPostData.AllocL();
	}
TBool CHTTPTransactionSource::GetNextDataPart(TPtrC8& aDataPart)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
		aDataPart.Set( *iPostData );
		return ETrue;	
	}
void CHTTPTransactionSource::ReleaseData()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	}
TInt CHTTPTransactionSource::OverallDataSize()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
		return iPostData->Length();
		//return KErrNotFound; // chunked transfer causes issues over my wi-fi, no idea why
	}
TInt CHTTPTransactionSource::Reset()
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);
		return KErrNotSupported;
	}

CHTTPTransactionSource::~CHTTPTransactionSource()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	delete iPostData;
	}


void RHTTPRequestSetHeaderL(RHTTPSession& aSession, RHTTPRequest aRequest, TInt aHdrField, const TDesC8& aHdrValue)
  {
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	RHTTPHeaders hdr = aRequest.GetHeaderCollection();
	RStringF valStr = aSession.StringPool().OpenFStringL(aHdrValue);
	CleanupClosePushL(valStr);
	THTTPHdrVal val(valStr);
	hdr.SetFieldL(aSession.StringPool().StringF(aHdrField,
		RHTTPSession::GetTable()), val);
	CleanupStack::PopAndDestroy();  // valStr
  }


RHTTPTransaction RHTTPSessionOpenTransactionL(RHTTPSession& aSession, const TDesC8& aUrl, MHTTPTransactionCallback& aCallback, TInt aMethod)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	TUriParser8 uri;
	uri.Parse( aUrl );
	RStringF method = aSession.StringPool().StringF(aMethod,RHTTPSession::GetTable());
	CleanupClosePushL(method);
	RHTTPTransaction transaction = aSession.OpenTransactionL(uri, aCallback, method);	
	CleanupStack::PopAndDestroy(&method);
	return transaction;
	}

TBool IsSpace(TChar ch)
	{
	switch(ch)
		{
		case ' ': case '\n': case '\t': case '\r':
			return ETrue;
			break;
		default:
			return EFalse;
		}
	}

TPtrC8 IrisTrim( const TDesC8& aBuf)
	{
	TInt beg, end;
	for(beg = 0 ; beg < aBuf.Length() && IsSpace( aBuf[beg] ) ; ++beg);
	if(beg == aBuf.Length()) return aBuf.Mid(0, 0);
	for(end = aBuf.Length() - 1 ; end > beg && IsSpace( aBuf[end] ) ; --end);
	return aBuf.Mid(beg, end + 1 - beg);
	}


TPtrC8 IrisExtractField(const TDesC8& aPrefix, const TDesC8& aSuffix, TPtrC8& aBuf)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	TPtrC8 ret;
	TInt begfield = aBuf.Find(aPrefix);
	if(begfield != KErrNotFound)
		{
		TInt endfield = aBuf.Mid(begfield + aPrefix.Length()).Find(aSuffix);
		if(endfield != KErrNotFound)
			{
			ret.Set( aBuf.Mid(begfield + aPrefix.Length(), endfield) );
			aBuf.Set( aBuf.Mid( begfield + aPrefix.Length() + endfield + aSuffix.Length() ) );
			return ret;
			}
		}
	aBuf.Set( aBuf.Mid( aBuf.Length() ) );
	return ret;
	}

